// 引入其他类
import Snake from "./Snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";

// 游戏控制器，控制其他的所有类
class GameControl {
  // 定义三个属性
  // 蛇
  snake: Snake;
  food: Food;
  scorePanel: ScorePanel;

  // 创建一个属性来存储蛇的移动方向（也就是按键的方向）
  direction: string = "";
  // 创建一个属性用来记录游戏是否结束
  isLive: boolean = true;

  constructor() {
    this.snake = new Snake();
    this.food = new Food();
    this.scorePanel = new ScorePanel();

    this.init();
  }

  // 游戏初始化方法，调用后游戏即开始
  init() {
    // 绑定键盘按下事件
    document.addEventListener("keydown", this.keydownHandle.bind(this));
    this.run();
  }

  /*
  Chrome           IE
  ArrowUp          Up
  ArrowDown       Down
  ArrowLeft       Left
  ArrowRight      Right
  */

  // 创建一个键盘按下的相应函数
  keydownHandle(event: KeyboardEvent) {
    // 修改direction属性
    this.direction = event.key;
  }

  // 创建一个控制蛇移动的方法
  run() {
    /* 根据方向（this.direction）来使蛇的位置改变
      向上 top 减少
      向下 top 增加
      向左 left 减少
      向右 left 增加
    */

    // 获取蛇现在的坐标
    let x: number = this.snake.X;
    let y: number = this.snake.Y;

    // 根据舍得方向计算坐标值
    switch (this.direction) {
      case "ArrowUp":
      case "Up":
      case "w":
      case "W":
        // 向上移动  top 减少
        y -= 10;
        break;
      case "ArrowDown":
      case "Down":
      case "s":
      case "S":
        // 向下移动 top 增加
        y += 10;
        break;
      case "ArrowLeft":
      case "Left":
      case "a":
      case "A":
        // 向左移动 left 减少
        x -= 10;
        break;
      case "ArrowRight":
      case "Right":
      case "d":
      case "D":
        // 向右移动 right 增加
        x += 10;
        break;
    }

    // 检查蛇是否吃到了食物
    this.checkEat(x, y);

    // 使用异常捕获来处理所有的游戏结束事件，减少代码
    try {
      // 修改蛇的位置
      this.snake.X = x;
      this.snake.Y = y;
    } catch (e: any) {
      // 进入到catch，说明出现了异常，游戏结束，弹出一个提示信息
      alert(e.message + "GAME OVER，请刷新页面后重新开始游戏");
      // 将isLive设置为false
      this.isLive = false;
    }

    // 开启一个定时调用
    this.isLive &&
      setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 30);
  }

  // 定义一个方法，用来检查蛇是否吃到了食物
  checkEat(x: number, y: number) {
    if (x === this.food.x && y === this.food.y) {
      // 食物的位置要进行重置
      this.food.change();
      // 分数增加
      this.scorePanel.addScore();
      // 蛇增加一节
      this.snake.addBody();
    }
  }
}

export default GameControl;

